import time
import struct
from machine import I2C, Pin


class wf100dpz:
    # scl: 时钟线, sda: 数据线, cs: 片选信号(低电平有效)
    def __init__(self, scl, sda, address=0x6d):
        self.i2c = I2C(1, scl=Pin(scl), sda=Pin(sda), freq=400000)
        self.address = address

    def start_sensor(self):
        self.cs.value(0)
        self._reset_sensor()                    # 调用软复位
        self.start_measurement()

    def stop_sensor(self):
        self.cs.value(1)

    def _write_register(self, reg, value):
        """写入8位寄存器数据"""
        self.i2c.writeto_mem(self.address, reg, bytearray([value]))

    def _read_register(self, reg, length=1, integer=False):
        """读取8位寄存器数据"""
        result = self.i2c.readfrom_mem(self.address, reg, length)
        if integer:
            ret = 0
            for item in result:
                ret = (ret << 8) | item
            return ret

        return result

    def _reset_sensor(self):
        """软复位并加载NVM校准数据"""
        # 0x30(CMD): RW, Sleep_time(4) | Sco | Measurement(3)
        # Measurement: 000: 单触发温度信号转换
        #              001: 单触发传感器信号转换
        #              010: 组合转换(1次温度转换后紧接传感器信号转换)
        #              011: 睡眠模式转换(周期性的执行一次组合转换, 间隔时间为Sleep_time)
        #              100: OTP编程模式
        # Sco: 1: 转换开始, 转换结束后自动返回0(睡眠模式转换除外)
        self._write_register(0x30, 0xb6)    # 软复位
        time.sleep(0.1)
        # 0x00(SPI_Ctrl): RW SDO_active | LSB_first | Softreset | - | - | Softreset | LSB_first | SDO_active
        # SDO_active: 1: 4线SPI, 0: 3线SPI
        # LSB_first: 1: LSB first SPI接口, 0: MSB first SPI接口
        # Softreset: 1: 重置所有寄存器, 重置完成后返回0
        self._write_register(0x00, 0x01)    # 启用I2C

    def start_measurement(self):
        """启动压力/温度转换"""
        # 00001010 -> Sleep_time = 0, Sco = 1(转换开始), Measurement = 010(组合转换)
        self._write_register(0x30, 0x0a)    # 转换控制寄存器

    def data_ready(self):
        """检查数据是否就绪"""
        return self._read_register(0x00, 1, True) & 0x08

    def read_pressure(self):
        """读取24位压力数据(Pa)"""
        # 0x06: DATA_MSB(气压值)
        # 0x07: DATA_CSB
        # 0x08: DATA_LSB
        raw = self._read_register(0x06, 3, True)
        return raw * 0.01

    def read_pressure_h(self):
        """计算校准后的压力值"""
        raw_pressure = self.read_pressure()
        raw_temperature = self.read_temperature()
        offset, span, temp_comp, nonlin = self._read_nvm_data()
        return (raw_pressure - offset) * span * (1 + temp_comp * raw_temperature) + nonlin * raw_pressure ** 2

    def read_temperature(self):
        """读取24位温度数据(°C)"""
        # 0x09: TEMP_MSB(温度值)
        # 0x0A: TEMP_LSB
        raw = self._read_register(0x09, 2, True)
        return raw * 0.01       # 转换为摄氏度

    def _read_nvm_data(self):
        """读取NVM校准数据"""
        raw = self._read_register(0x40, 16)
        return struct.unpack("<4f", raw)


if __name__ == "__main__":
    sensor = wf100dpz(13, 14, 15)
    sensor.start_measurement()
    while not sensor.data_ready():
        time.sleep(0.1)
    pressure = sensor.read_pressure()           # 读取压力值
    temperature = sensor.read_temperature()     # 读取温度值